/******************************************************************
文件名	：font.c
功能 	：用于在LCD上显示任意字（粤嵌6818）
版本	：1.0
时间	：2017.10.19
作者	：王理洁
联系方式：wanglijie201710@163.com
******************************************************************/



#include "font.h"

/***************************************************************
函数名：open_font_file
功能： 	打开字体文件
参数： 	const char 	*font_file_name：字库文件名 
返回值：fd_fl  成功则返回文件句柄
		NULL   失败则返回NULL    
***************************************************************/
FILE* open_font_file(const char *font_file_name)
{	
	FILE *	fd_fl = fopen(font_file_name, "rb");	// “rb”: 以只读方式打开二进制文件
	if(NULL == fd_fl)
	{
		perror("open font file");
		return NULL;		
	}

	return fd_fl;
}

/***************************************************************
函数名：read_fl_header
功能： 	读文件头信息和段信息,写入头结构体中
参数： 	pFL_HEADER fd_header	头结构体地址
		FILE *fd_fl				字库文件指针
返回值：0 ：	成功
		-1：	失败     
***************************************************************/
u32 read_fl_header(pFL_HEADER fl_header, FILE *fd_fl)
{
	
	memset(fl_header,0,sizeof(FL_HEADER));
	int ret;
	fread(fl_header,16,1,fd_fl);		//读16 byte 文件头  fd_fl: 字库文件的句柄
	if(	fl_header->tag[0] != 'U' ||
		fl_header->tag[1] != 'F' || 
		fl_header->tag[2] != 'L')		//判断是否为 UNICODE 编码格式的字库文件
	{
		printf("read fl header:format error\n");			//如果不是，打印错误信息，并返回错误
		
		return -1;		
	}
		
	fl_header->psection = (pFL_SECTION_INF)malloc(fl_header->section_count * sizeof(FL_SECTION_INF));
										//为段（section）信息节构体分配空间  fl_header.section_count：有几个section
	if(NULL == fl_header->psection)
	{
		perror("malloc error");
		return -1;
	}
	
	ret = fread(fl_header->psection,sizeof(FL_SECTION_INF),fl_header->section_count,fd_fl);
	if(ret != fl_header->section_count)
	{
		perror("read section infos");
		return -1;		
	}
	
	return 0;
}




/***************************************************************
函数名：read_char_info
功能： 	读取目标字符的检索信息
参数： 	u16 char_code：			指定字符的编码
		pFL_HEADER fl_header：	字库文件头结构体地址
		FILE *fd_fl：			字库文件指针
返回值：char_info：	成功则返回检索信息
		-1：		失败则返回-1
***************************************************************/
u32 read_char_info(u16 char_code, pFL_HEADER fl_header, FILE *fd_fl)
{
	u32 offset;										//char_code 这个字符的检索信息在整个字库中的偏移（offset），即它（的检索信息）所在的位置
	u32 i;
	u32 char_info = 0;
	
	for(i = 0; i < fl_header->section_count; i++)	//遍历所有段（section）
	{
		if(char_code >= fl_header->psection[i].first  &&  char_code <= fl_header->psection[i].last)
													//判断wCode 这个字符是否在当前段（section）内
		break;
	}
	if(i > fl_header->section_count)
	{
		printf("not found this char");
		return -1;
	}

	offset = fl_header->psection[i].offaddr + FONT_INFO_SIZE*(char_code - fl_header->psection[i].first);
													//计算 char_code 这个字符在整个字库中的偏移（offset）,即找到它（的检索信息）所在的位置
													//_fl_header.pSection[i].OffAddr  	当前段在整个字库文件中的offset
													//FONT_INDEX_TAB_SIZE				每个字符的检索信息占的字节长度 4 byte
													//char_code								目标字符的编码
													//_fl_header.pSection[i].First		当前段第一个字符的编码
	fseek(fd_fl, offset, SEEK_SET);					//光标在字库中移动，光标移动到char_code这个字所在的位置，g_prf 是字库的句柄
	fread(&char_info, sizeof(char_info),1,fd_fl);	//读取 char_code 这个的检索信息
	return char_info;
}
/***************************************************************
函数名：read_char_dot_matix
功能： 	读目标字符的点阵信息
参数： 	u32 char_info:	指定字符的检索信息
		u8* buf:		存放点阵信息的buffer	
		FILE *fd_fl:	字库文件指针
返回值：无     
***************************************************************/
int read_char_dot_matix(u32 char_info, u8* buf,pFL_HEADER fl_header, FILE *fd_fl)
{
	u32 byte_per_line = 0;
	int ret = 0;
	u32 offset = 0;
	if(0 == char_info)
	{
		printf("read char dot maxtrix: wrong char code");
		return -1;
		
	}
	offset = char_info & 0x03ffffff;
	byte_per_line = (u32)((  (char_info >> 26) + 7 ) / PIXE_PER_BYTE);//点阵的每一行有多少位（宽度+7）/（像素/byte）  加7为了避免宽度小于8时得到0
	//memset(buf,0,sizeof(buf));
	fseek(fd_fl,offset,SEEK_SET);
	ret = fread(buf, byte_per_line,fl_header->height, fd_fl);
	if(fl_header->height != ret)
	{
		printf("read char dot maxtrix: read error");
		return -1;		
	}
	
	return 0;	
}

/***************************************************************
函数名：utf8_to_unicode
功能： 	将一串UTF8字符编码（linux系统默认）转化为 unicode字符编码（字库的字符编码）
参数： 	char *utf8		UTF8编码存放地址
返回值：unicode			转化后的unicode 码存放地址
***************************************************************/
u32* utf8_to_unicode(char *utf8)
{
	u32 lenth = strlen(utf8);
	u32 *unicode;
	int i,j,n;
	//printf("utf8_to_unicode: strint length in utf8:		%d\n",lenth);
	for(i=0,n=0;i<lenth;i++)
	{
		if(	0 == (utf8[i] & 0x80) )//0x7f = 0111 1111
			n++;
	}
	lenth = n + (lenth-n)/3;
	//printf("utf8_to_unicode: strint length in unicode: 	%d\n",lenth);

	unicode = calloc(lenth+1,sizeof(u32));
	
	for(i=0,j=0;i<lenth;i++)
	{
		if((utf8[j] & 0x80) != 0 )	//0x7f = 0111 1111
		{
		unicode[i] = (  (utf8[j] & 0x0f) << 12   |   (utf8[j+1] & 0x3f) << 6   |   (utf8[j+2] & 0x3f)  );
		j+=3;
		}
		else
		{
			unicode[i] = utf8[j];
			j++;
		}
	//printf("utf8_to_unicode: unicode[%d]: 0x%x\n",i,unicode[i]);	
		
	}
	unicode[i] = 0;
	return unicode;
	
}




